﻿#define _CRT_SECURE_NO_WARNINGS 1

//#include <stdio.h>
//int main()
//{
//	char* p = "abcdef";//常量字符串，指针变量p中存放的是首字符a的地址
//	printf("%zd\n", sizeof(p));//指针变量的大小取决于地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(p + 1));//第二个字符b的地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(*p));//字符a的大小，1个字节
//	printf("%zd\n", sizeof(p[0]));
//	//法一：p[0] == *(p + 0) == *p，大小为1个字节
//	//法二：p是首元素的地址，相当于数组名，把常量字符串当成一个数组，p[0]就是第一个元素a
//	printf("%zd\n", sizeof(&p));//指针变量p的地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(&p + 1));//跳过一个指针变量p的大小的地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(&p[0] + 1));
//	//p[0] == *(p + 0) == *p == a
//	// &p[0] == p ,&p[0] + 1 == p + 1,char* 类型的指针变量+1，跳过1个字节
//	// 即计算的是第二个元素b的地址的大小，是地址就是4/8个字节
//	return 0;
//}



//#include <stdio.h>
//#include <string.h>
//int main()
//{
//	char* p = "abcdef";
//	//[abcdef\0]
//	printf("%zd\n", strlen(p));//6
//	printf("%zd\n", strlen(p + 1));//char*类型的地址+1，跳过1个字节，从第二个地址开始往后数，5
//	printf("%zd\n", strlen(*p));//*p == 'a' == 97,strlen()会把97当成地址，这时就是非法访问，err
//	printf("%zd\n", strlen(p[0]));//p[0] == a，理由同上，err
//	printf("%zd\n", strlen(&p));//从指针变量p的地址开始往后数，随机值
//	printf("%zd\n", strlen(&p + 1));//地址+1，就跳过一个地址所指的元素，所以从地址&p + 1开始往后数，随机值
//	printf("%zd\n", strlen(&p[0] + 1));//&p[0] + 1 == p + 1，5
//	return 0;
//}



//#include <stdio.h>
//#include <string.h>
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", strlen(arr));
//	printf("%zd\n", strlen(arr + 0));
//	//printf("%zd\n", strlen(*arr));
//	//printf("%zd\n", strlen(arr[1]));
//	printf("%zd\n", strlen(&arr));
//	printf("%zd\n", strlen(&arr + 1));
//	printf("%zd\n", strlen(&arr[0] + 1));
//	return 0;
//}



//#include <stdio.h>
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//数组名单独放在sizeof()中，计算的是整个数组的大小，48个字节
//	printf("%zd\n", sizeof(a[0][0]));//二维数组中第一行第一个元素的大小，4个字节
//	printf("%zd\n", sizeof(a[0]));
//	//a[0]相当于第一行数组的数组名，数组名单独放在sizeof()中，计算的是整个第一行一维数组的大小，16个字节
//	printf("%zd\n", sizeof(a[0] + 1));
//	//a[0]是第一行一维数组的数组名，因为数组名没有单独放在sizeof()中，所以a[0]是第一行一维数组的首元素a[0][0]的地址
//	//a[0]的类型是int*类型，a[0] + 1，跳过4个字节，即二维数组中第二个元素a[0][1]的地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(*(a[0] + 1)));//*(a[0] + 1)是二维数组中第二个元素a[0][1]，计算的是一个元素的大小，4个字节
//	printf("%zd\n", sizeof(a + 1));
//	//二维数组数组名a没有单独放在sizeof()中，所以a表示第一行一维数组的地址
//	//这里a的类型是int(*)[4]，地址+1，跳过整个第一行一维数组，指向第二行一维数组，a + 1的类型也是int(*)[4]
//	//所以求的是第二行一维数组的地址的大小，是地址就是4/8个字节
//	printf("%zd\n", sizeof(*(a + 1)));//*(a + 1)表示整个第二行一维数组的大小，16个字节
//	printf("%zd\n", sizeof(&a[0] + 1));
//	//&a[0]是整个第一行一维数组的地址，&a[0] + 1表示跳过一整个一维数组的地址，也就是第二行一维数组的地址
//	//是地址就是4/8个字节
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//整个第二行一维数组的大小，16个字节
//	printf("%zd\n", sizeof(*a));//a表示第一行一维数组的地址，*a为第一行一维数组的大小，16个字节
//	printf("%zd\n", sizeof(a[3]));//sizeof()不关注内存中存放什么数据，
//	//a[3] 类似 a[2]、a[1]、a[0]， 16个字节
//	//sizeof在计算的时候是根据类型来计算长度的，即使你写的是一个表达式，编译器也会推算出最终的类型，来计算长度
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));
//	return 0;
//}
////程序的结果是什么？


//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥？
#include <stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;//0x开头的是16进制数字
int main()
{
	printf("%p\n", p + 0x1);
	//0x1，16进制的1，就表示的是1。p + 0x1 表示结构体指针+1，就跳过一整个结构体，跳过20个字节
	//10进制的20转换成16进制是0x14，p + 0x1 == 0x100000 + 0x14 == 0x100014
	printf("%p\n", (unsigned long)p + 0x1);
	//p不是指针了，强制类型转换成了无符号长整型
	//(unsigned long)p + 0x1 == 0x100000 + 0x1 == 0x100001
	printf("%p\n", (unsigned int*)p + 0x1);
	//struct Test*类型的p强制类型转换成了unsigned int*
	//(unsigned long)p + 0x1意思是：unsigned int*类型的地址+1，跳过4个字节
	//10进制的4转换成16进制是0x4，(unsigned int*)p + 0x1 == 0x100000 + 0x4 == 0x100004
	return 0;
}











